/******************************************************************************

  Copyright (C), Hisilicon Tech. Co., Ltd.

 ******************************************************************************
  File Name     : sample_venc.c
  Version       : Initial Draft
  Author        : Hisilicon multimedia software group
  Created       : 
  Description   :
******************************************************************************/

#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif /* End of #ifdef __cplusplus */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <signal.h>

#include "rtsp_demo.h"
#include "comm.h"
#include "sample_comm.h"
#include "sample_audio.h"
#include "audio_aac_adp.h"
#include "hh_osd.h"
#include "onvif_server.h"

#include "mp4v2_record.h"
#include <libwebsockets.h>
#include "capture.h"
#include "network_common.h"
#include "hh_osd_api.h"
#include "rtsp_server.h"
#include "mp4_to_h264.h"
#include "mp4v2_record.h"

// #include "network_tcp.h"
// #include "serial_uart.h"
// #include "http_init.h"
// #include "discovery_private_device.h"

#define BIG_STREAM_SIZE_BT656        PIC_D1_PAL
#define BIG_STREAM_SIZE_IMX335       PIC_2592x1520
// PIC_2688x1944
#define SMALL_STREAM_SIZE   PIC_640x512
// PIC_640x512  
//PIC_640x512
#define SMALL_SMALL_STREAM_SIZE   PIC_384x288
//PIC_720P
// PIC_1080P
#define    FPGA_DEVICE  "/dev/ttyAMA1"

#define VB_MAX_NUM            10
#define ONLINE_LIMIT_WIDTH    2304

#define WRAP_BUF_LINE_EXT     416
#define MAX_NALU_SIZE (640*512*3)
static pthread_t VencPid;
rtsp_demo_handle g_rtsplive = NULL;
rtsp_session_handle session= NULL;
rtsp_session_handle g_playback_session = NULL;

CaptureInfo_S state;
extern  NaluQueue g_nalu_queue;
extern  RecorderState g_recorder_state;
// NetworkContorlOSDShowState osdShow;
NetworkConfigOtherPreview otherPreview;
int osd_switch = 1;
extern int init_osd_flag;
int g_stopStreaming = 0;
extern int ldc_type;
extern int ldc_value;
extern int frame_rate;

typedef struct hiSAMPLE_VPSS_ATTR_S
{
    SIZE_S            stMaxSize;
    DYNAMIC_RANGE_E   enDynamicRange;
    PIXEL_FORMAT_E    enPixelFormat;
    COMPRESS_MODE_E   enCompressMode[VPSS_MAX_PHY_CHN_NUM];
    SIZE_S            stOutPutSize[VPSS_MAX_PHY_CHN_NUM];
    FRAME_RATE_CTRL_S stFrameRate[VPSS_MAX_PHY_CHN_NUM];
    HI_BOOL           bMirror[VPSS_MAX_PHY_CHN_NUM];
    HI_BOOL           bFlip[VPSS_MAX_PHY_CHN_NUM];
    HI_BOOL           bChnEnable[VPSS_MAX_PHY_CHN_NUM];

    SAMPLE_SNS_TYPE_E enSnsType;
    HI_U32            BigStreamId;
    HI_U32            SmallStreamId;
    VI_VPSS_MODE_E    ViVpssMode;
    HI_BOOL           bWrapEn;
    HI_U32            WrapBufLine;
} SAMPLE_VPSS_CHN_ATTR_S;

typedef struct hiSAMPLE_VB_ATTR_S
{
    HI_U32            validNum;
    HI_U64            blkSize[VB_MAX_NUM];
    HI_U32            blkCnt[VB_MAX_NUM];
    HI_U32            supplementConfig;
} SAMPLE_VB_ATTR_S;


typedef struct {
	int record_flag;
	RtspServerRecordInfo record_info;
}Mng;

typedef struct {
	int record_enable;
	char filename[128];				// 文件名
	int offset_time;				// 录像偏移时间，单位：秒
}Record_S;

enum {
    enViewType = 0,
    s32CenterXOffset,
    s32CenterYOffset,
    s32DistortionRatio,
    s32MinRatio,
    bEnable,
    ldc_number
};

static Mng g_mng;
static Record_S g_record;

/******************************************************************************
* function : to process abnormal case
******************************************************************************/
void SAMPLE_VENC_HandleSig(HI_S32 signo)
{
    // signal(SIGINT, SIG_IGN);
    // signal(SIGTERM, SIG_IGN);

    if (SIGINT == signo || SIGTERM == signo )
    {
        osd_switch = 0;
        // SAMPLE_COMM_VENC_StopSendQpmapFrame();
        SAMPLE_COMM_VENC_StopGetStream();
        SAMPLE_COMM_All_ISP_Stop();
        SAMPLE_COMM_SYS_Exit();
        printf("\033[0;31mprogram termination abnormally [%d]!\033[0;39m\n",signo);
    }

    // if(session){
    //     rtsp_del_session(session);
    // }else{
    //     rtsp_del_demo(g_rtsplive);
    // }


    exit(-1);
}

/******************************************************************************
* function : to process abnormal case - the case of stream venc
******************************************************************************/
void SAMPLE_VENC_StreamHandleSig(HI_S32 signo)
{
    if (SIGINT == signo || SIGTERM == signo)
    {
        SAMPLE_COMM_SYS_Exit();
        printf("\033[0;31mprogram exit abnormally!\033[0;39m\n");
    }

    exit(0);
}

VENC_GOP_MODE_E SAMPLE_VENC_GetGopMode(void)
{
   // char c;
    VENC_GOP_MODE_E enGopMode = 0;

// Begin_Get:

    // printf("please input choose gop mode!\n");
    // printf("\t 0) NORMALP.\n");
    // printf("\t 1) DUALP.\n");
    // printf("\t 2) SMARTP.\n");

    // while((c = getchar()) != '\n' && c != EOF)
    // switch(c)
    // {
        // case '0':
            enGopMode = VENC_GOPMODE_NORMALP;
            // break;
        // case '1':
            // enGopMode = VENC_GOPMODE_DUALP;
            // break;
        // case '2':
            // enGopMode = VENC_GOPMODE_SMARTP;
            // break;
        // default:
            // SAMPLE_PRT("input rcmode: %c, is invaild!\n",c);
            // goto Begin_Get;
    // }

    return enGopMode;
}

SAMPLE_RC_E SAMPLE_VENC_GetRcMode(void)
{
    // char c;
    SAMPLE_RC_E  enRcMode = 0;

// Begin_Get:

    // printf("please input choose rc mode!\n");
    // printf("\t c) cbr.\n");
    // printf("\t v) vbr.\n");
    // printf("\t a) avbr.\n");
    // printf("\t x) cvbr.\n");
    // printf("\t q) qvbr.\n");
    // printf("\t f) fixQp\n");

    // while((c = getchar()) != '\n' && c != EOF)
    // switch(c)
    // {
        // case 'c':
            enRcMode = SAMPLE_RC_CBR;
            // break;
        // case 'v':
            // enRcMode = SAMPLE_RC_VBR;
            // break;
        // case 'a':
            // enRcMode = SAMPLE_RC_AVBR;
            // break;
        // case 'f':
            // enRcMode = SAMPLE_RC_FIXQP;
            // break;
        // case 'x':
            // enRcMode = SAMPLE_RC_CVBR;
            // break;
        // case 'q':
            // enRcMode = SAMPLE_RC_QVBR;
            // break;
        // default:
            // SAMPLE_PRT("input rcmode: %c, is invaild!\n",c);
            // goto Begin_Get;
    // }
    return enRcMode;
}

static HI_U32 GetFrameRateFromSensorType(SAMPLE_SNS_TYPE_E enSnsType)
{
    HI_U32 FrameRate;

    SAMPLE_COMM_VI_GetFrameRateBySensor(enSnsType, &FrameRate);

    return FrameRate;
}

static HI_U32 GetFullLinesStdFromSensorType(SAMPLE_SNS_TYPE_E enSnsType)
{
    HI_U32 FullLinesStd = 0;

    switch (enSnsType)
    {
        case SONY_IMX327_MIPI_2M_30FPS_12BIT:
        case SONY_IMX327_MIPI_2M_30FPS_12BIT_WDR2TO1:
            FullLinesStd = 1125;
            break;
        case SONY_IMX307_MIPI_2M_30FPS_12BIT:
        case SONY_IMX307_MIPI_2M_30FPS_12BIT_WDR2TO1:
        case SONY_IMX307_2L_MIPI_2M_30FPS_12BIT:
        case SONY_IMX307_2L_MIPI_2M_30FPS_12BIT_WDR2TO1:
        case SMART_SC2235_DC_2M_30FPS_10BIT:
        case SMART_SC2231_MIPI_2M_30FPS_10BIT:
            FullLinesStd = 1125;
            break;
        case SONY_IMX335_MIPI_5M_30FPS_12BIT:
        case SONY_IMX335_MIPI_5M_30FPS_10BIT_WDR2TO1:
            FullLinesStd = 1875;
            break;
        case SONY_IMX335_MIPI_4M_30FPS_12BIT:
        case SONY_IMX335_MIPI_4M_30FPS_10BIT_WDR2TO1:
            FullLinesStd = 1375;
            break;
        case SMART_SC4236_MIPI_3M_30FPS_10BIT:
        case SMART_SC4236_MIPI_3M_20FPS_10BIT:
            FullLinesStd = 1600;
            break;
        case GALAXYCORE_GC2053_MIPI_2M_30FPS_10BIT:
        case GALAXYCORE_GC2053_MIPI_2M_30FPS_10BIT_FORCAR:
            FullLinesStd = 1108;
            break;
        default:
            SAMPLE_PRT("Error: Not support this sensor now! ==> %d\n",enSnsType);
            break;
    }

    return FullLinesStd;
}

static HI_VOID AdjustWrapBufLineBySnsType(SAMPLE_SNS_TYPE_E enSnsType, HI_U32 *pWrapBufLine)
{
    /*some sensor as follow need to expand the wrapBufLine*/
    if ((enSnsType == SMART_SC4236_MIPI_3M_30FPS_10BIT) ||
        (enSnsType == SMART_SC4236_MIPI_3M_20FPS_10BIT) ||
        (enSnsType == SMART_SC2235_DC_2M_30FPS_10BIT))
    {
        *pWrapBufLine += WRAP_BUF_LINE_EXT;
    }

    return;
}

static HI_VOID GetSensorResolution(SAMPLE_SNS_TYPE_E enSnsType, SIZE_S *pSnsSize)
{
    HI_S32          ret;
    SIZE_S          SnsSize;
    PIC_SIZE_E      enSnsSize;

    ret = SAMPLE_COMM_VI_GetSizeBySensor(enSnsType, &enSnsSize);
    if (HI_SUCCESS != ret)
    {
        SAMPLE_PRT("SAMPLE_COMM_VI_GetSizeBySensor failed!\n");
        return;
    }
    ret = SAMPLE_COMM_SYS_GetPicSize(enSnsSize, &SnsSize);
    if (HI_SUCCESS != ret)
    {
        SAMPLE_PRT("SAMPLE_COMM_SYS_GetPicSize failed!\n");
        return;
    }

    *pSnsSize = SnsSize;

    return;
}

static HI_VOID GetVpssWrapBufLine(SAMPLE_VPSS_CHN_ATTR_S *pParam)
{
    HI_U32 vpssWrapBufLine = 0;

    VPSS_VENC_WRAP_PARAM_S wrapParam;

    memset(&wrapParam, 0, sizeof(VPSS_VENC_WRAP_PARAM_S));
    wrapParam.bAllOnline      = (pParam->ViVpssMode == VI_ONLINE_VPSS_ONLINE) ? 1 : 0;
    wrapParam.u32FrameRate    = GetFrameRateFromSensorType(pParam->enSnsType);
    wrapParam.u32FullLinesStd = GetFullLinesStdFromSensorType(pParam->enSnsType);
    wrapParam.stLargeStreamSize.u32Width = pParam->stOutPutSize[pParam->BigStreamId].u32Width;
    wrapParam.stLargeStreamSize.u32Height= pParam->stOutPutSize[pParam->BigStreamId].u32Height;
    wrapParam.stSmallStreamSize.u32Width = pParam->stOutPutSize[pParam->SmallStreamId].u32Width;
    wrapParam.stSmallStreamSize.u32Height= pParam->stOutPutSize[pParam->SmallStreamId].u32Height;

    if (HI_MPI_SYS_GetVPSSVENCWrapBufferLine(&wrapParam, &vpssWrapBufLine) != HI_SUCCESS)
    {
        SAMPLE_PRT("Error:Current BigStream(%dx%d@%d fps) and SmallStream(%dx%d@%d fps) not support Ring!== return 0x%x(0x%x)\n",
            wrapParam.stLargeStreamSize.u32Width,wrapParam.stLargeStreamSize.u32Height,wrapParam.u32FrameRate,
            wrapParam.stSmallStreamSize.u32Width,wrapParam.stSmallStreamSize.u32Height,wrapParam.u32FrameRate,
            HI_MPI_SYS_GetVPSSVENCWrapBufferLine(&wrapParam, &vpssWrapBufLine), HI_ERR_SYS_NOT_SUPPORT);
        vpssWrapBufLine = 0;
    }
    else
    {
        AdjustWrapBufLineBySnsType(pParam->enSnsType, &vpssWrapBufLine);
    }

    pParam->WrapBufLine = vpssWrapBufLine;

    return;
}

static VI_VPSS_MODE_E GetViVpssModeFromResolution(SAMPLE_SNS_TYPE_E SnsType)
{
    SIZE_S SnsSize = {0};
    VI_VPSS_MODE_E ViVpssMode;

    GetSensorResolution(SnsType, &SnsSize);

    if (SnsSize.u32Width > ONLINE_LIMIT_WIDTH)
    {
        ViVpssMode = VI_OFFLINE_VPSS_ONLINE; //for imx335
    }
    else
    {
        ViVpssMode = VI_ONLINE_VPSS_ONLINE;
    }

    if(BT656_2M_30FPS_8BIT == SnsType){
        ViVpssMode = VI_ONLINE_VPSS_OFFLINE;//only for bt656
    }

    return ViVpssMode;
}

static HI_VOID SAMPLE_VENC_GetDefaultVpssAttr(SAMPLE_SNS_TYPE_E enSnsType, HI_BOOL *pChanEnable, SIZE_S stEncSize[], SAMPLE_VPSS_CHN_ATTR_S *pVpssAttr)
{
    HI_S32 i;

    memset(pVpssAttr, 0, sizeof(SAMPLE_VPSS_CHN_ATTR_S));

    pVpssAttr->enDynamicRange = DYNAMIC_RANGE_SDR8;
    pVpssAttr->enPixelFormat  = PIXEL_FORMAT_YVU_SEMIPLANAR_420;
    pVpssAttr->bWrapEn        = 0;
    pVpssAttr->enSnsType      = enSnsType;
    pVpssAttr->ViVpssMode     = GetViVpssModeFromResolution(enSnsType);

    for (i = 0; i < VPSS_MAX_PHY_CHN_NUM; i++)
    {
        if (HI_TRUE == pChanEnable[i])
        {
            pVpssAttr->enCompressMode[i]          = (i == 0)? COMPRESS_MODE_SEG : COMPRESS_MODE_NONE;
            pVpssAttr->stOutPutSize[i].u32Width   = stEncSize[i].u32Width;
            pVpssAttr->stOutPutSize[i].u32Height  = stEncSize[i].u32Height;
            pVpssAttr->stFrameRate[i].s32SrcFrameRate  = 25;
            pVpssAttr->stFrameRate[i].s32DstFrameRate  = 25;
            pVpssAttr->bMirror[i]                      = HI_FALSE;
            pVpssAttr->bFlip[i]                        = HI_FALSE;

            pVpssAttr->bChnEnable[i]                   = HI_TRUE;
        }
    }

    return;
}

HI_S32 SAMPLE_VENC_SYS_Init(SAMPLE_VB_ATTR_S *pCommVbAttr)
{
    HI_S32 i;
    HI_S32 s32Ret;
    VB_CONFIG_S stVbConf;

    if (pCommVbAttr->validNum > VB_MAX_COMM_POOLS)
    {
        SAMPLE_PRT("SAMPLE_VENC_SYS_Init validNum(%d) too large than VB_MAX_COMM_POOLS(%d)!\n", pCommVbAttr->validNum, VB_MAX_COMM_POOLS);
        return HI_FAILURE;
    }

    memset(&stVbConf, 0, sizeof(VB_CONFIG_S));

    for (i = 0; i < pCommVbAttr->validNum; i++)
    {
        stVbConf.astCommPool[i].u64BlkSize   = pCommVbAttr->blkSize[i];
        stVbConf.astCommPool[i].u32BlkCnt    = 7;//pCommVbAttr->blkCnt[i];
        //printf("%s,%d,stVbConf.astCommPool[%d].u64BlkSize = %lld, blkSize = %d\n",__func__,__LINE__,i,stVbConf.astCommPool[i].u64BlkSize,stVbConf.astCommPool[i].u32BlkCnt);
    }

    stVbConf.u32MaxPoolCnt = pCommVbAttr->validNum;

    if(pCommVbAttr->supplementConfig == 0)
    {
        s32Ret = SAMPLE_COMM_SYS_Init(&stVbConf);
    }
    else
    {
        s32Ret = SAMPLE_COMM_SYS_InitWithVbSupplement(&stVbConf,pCommVbAttr->supplementConfig);
    }

    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("SAMPLE_COMM_SYS_GetPicSize failed!\n");
        return s32Ret;
    }

    // init_flag = 1;
    return HI_SUCCESS;
}

HI_VOID SAMPLE_VENC_SetDCFInfo(VI_PIPE ViPipe)
{
    ISP_DCF_INFO_S stIspDCF;

    HI_MPI_ISP_GetDCFInfo(ViPipe, &stIspDCF);

    //description: Thumbnail test
    strncpy((char *)stIspDCF.stIspDCFConstInfo.au8ImageDescription,"Thumbnail test",DCF_DRSCRIPTION_LENGTH);
    //manufacturer: Hisilicon
    strncpy((char *)stIspDCF.stIspDCFConstInfo.au8Make,"Hisilicon",DCF_DRSCRIPTION_LENGTH);
    //model number: Hisilicon IP Camera
    strncpy((char *)stIspDCF.stIspDCFConstInfo.au8Model,"Hisilicon IP Camera",DCF_DRSCRIPTION_LENGTH);
    //firmware version: v.1.1.0
    strncpy((char *)stIspDCF.stIspDCFConstInfo.au8Software,"v.1.1.0",DCF_DRSCRIPTION_LENGTH);


    stIspDCF.stIspDCFConstInfo.u32FocalLength             = 0x00640001;
    stIspDCF.stIspDCFConstInfo.u8Contrast                 = 5;
    stIspDCF.stIspDCFConstInfo.u8CustomRendered           = 0;
    stIspDCF.stIspDCFConstInfo.u8FocalLengthIn35mmFilm    = 1;
    stIspDCF.stIspDCFConstInfo.u8GainControl              = 1;
    stIspDCF.stIspDCFConstInfo.u8LightSource              = 1;
    stIspDCF.stIspDCFConstInfo.u8MeteringMode             = 1;
    stIspDCF.stIspDCFConstInfo.u8Saturation               = 1;
    stIspDCF.stIspDCFConstInfo.u8SceneCaptureType         = 1;
    stIspDCF.stIspDCFConstInfo.u8SceneType                = 0;
    stIspDCF.stIspDCFConstInfo.u8Sharpness                = 5;
    stIspDCF.stIspDCFUpdateInfo.u32ISOSpeedRatings         = 500;
    stIspDCF.stIspDCFUpdateInfo.u32ExposureBiasValue       = 5;
    stIspDCF.stIspDCFUpdateInfo.u32ExposureTime            = 0x00010004;
    stIspDCF.stIspDCFUpdateInfo.u32FNumber                 = 0x0001000f;
    stIspDCF.stIspDCFUpdateInfo.u8WhiteBalance             = 1;
    stIspDCF.stIspDCFUpdateInfo.u8ExposureMode             = 0;
    stIspDCF.stIspDCFUpdateInfo.u8ExposureProgram          = 1;
    stIspDCF.stIspDCFUpdateInfo.u32MaxApertureValue        = 0x00010001;

    HI_MPI_ISP_SetDCFInfo(ViPipe, &stIspDCF);

    return;
}

HI_S32 SAMPLE_VENC_VI_Init( SAMPLE_VI_CONFIG_S *pstViConfig, VI_VPSS_MODE_E ViVpssMode)
{
    HI_S32              s32Ret;
    SAMPLE_SNS_TYPE_E   enSnsType;
    ISP_CTRL_PARAM_S    stIspCtrlParam;
    HI_U32              u32FrameRate;


    enSnsType = pstViConfig->astViInfo[0].stSnsInfo.enSnsType;

    pstViConfig->as32WorkingViId[0]                           = 0;

    pstViConfig->astViInfo[0].stSnsInfo.MipiDev            = SAMPLE_COMM_VI_GetComboDevBySensor(pstViConfig->astViInfo[0].stSnsInfo.enSnsType, 0);
    pstViConfig->astViInfo[0].stSnsInfo.s32BusId           = 0;
    pstViConfig->astViInfo[0].stDevInfo.enWDRMode          = WDR_MODE_NONE;
    pstViConfig->astViInfo[0].stPipeInfo.enMastPipeMode    = ViVpssMode;

    //pstViConfig->astViInfo[0].stPipeInfo.aPipe[0]          = ViPipe0;
    pstViConfig->astViInfo[0].stPipeInfo.aPipe[1]          = -1;

    //pstViConfig->astViInfo[0].stChnInfo.ViChn              = ViChn;
    // pstViConfig->astViInfo[0].stChnInfo.enPixFormat        = PIXEL_FORMAT_YVU_SEMIPLANAR_420;//test
    //pstViConfig->astViInfo[0].stChnInfo.enDynamicRange     = enDynamicRange;
    pstViConfig->astViInfo[0].stChnInfo.enVideoFormat      = VIDEO_FORMAT_LINEAR;
    pstViConfig->astViInfo[0].stChnInfo.enCompressMode     = COMPRESS_MODE_NONE;
    s32Ret = SAMPLE_COMM_VI_SetParam(pstViConfig);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("SAMPLE_COMM_VI_SetParam failed with %d!\n", s32Ret);
        return s32Ret;
    }

    SAMPLE_COMM_VI_GetFrameRateBySensor(enSnsType, &u32FrameRate);
    SAMPLE_PRT("SAMPLE_COMM_VI_GetFrameRateBySensor  with fps:[%d]!\n", u32FrameRate);

    s32Ret = HI_MPI_ISP_GetCtrlParam(pstViConfig->astViInfo[0].stPipeInfo.aPipe[0], &stIspCtrlParam);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("HI_MPI_ISP_GetCtrlParam failed with %d!\n", s32Ret);
        return s32Ret;
    }
    

    stIspCtrlParam.u32StatIntvl  = u32FrameRate/30;
    if (stIspCtrlParam.u32StatIntvl == 0)
    {
        stIspCtrlParam.u32StatIntvl = 1;
    }

    s32Ret = HI_MPI_ISP_SetCtrlParam(pstViConfig->astViInfo[0].stPipeInfo.aPipe[0], &stIspCtrlParam);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("HI_MPI_ISP_SetCtrlParam failed with %d!\n", s32Ret);
        return s32Ret;
    }

    s32Ret = SAMPLE_COMM_VI_StartVi(pstViConfig);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_COMM_SYS_Exit();
        SAMPLE_PRT("SAMPLE_COMM_VI_StartVi failed with %d!\n", s32Ret);
        return s32Ret;
    }

    return HI_SUCCESS;
}

static HI_S32 SAMPLE_VENC_VPSS_CreateGrp(VPSS_GRP VpssGrp, SAMPLE_VPSS_CHN_ATTR_S *pParam)
{
    HI_S32          s32Ret;
    PIC_SIZE_E      enSnsSize;
    SIZE_S          stSnsSize;
    VPSS_GRP_ATTR_S stVpssGrpAttr = {0};

    s32Ret = SAMPLE_COMM_VI_GetSizeBySensor(pParam->enSnsType, &enSnsSize);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("SAMPLE_COMM_VI_GetSizeBySensor failed!\n");
        return s32Ret;
    }

    s32Ret = SAMPLE_COMM_SYS_GetPicSize(enSnsSize, &stSnsSize);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("SAMPLE_COMM_SYS_GetPicSize failed!\n");
        return s32Ret;
    }

    stVpssGrpAttr.enDynamicRange          = pParam->enDynamicRange;
    stVpssGrpAttr.enPixelFormat           = pParam->enPixelFormat;
    stVpssGrpAttr.u32MaxW                 = stSnsSize.u32Width;
    stVpssGrpAttr.u32MaxH                 = stSnsSize.u32Height;
    stVpssGrpAttr.bNrEn                   = HI_TRUE;
    stVpssGrpAttr.stNrAttr.enNrType       = VPSS_NR_TYPE_VIDEO;
    stVpssGrpAttr.stNrAttr.enNrMotionMode = NR_MOTION_MODE_NORMAL;
    stVpssGrpAttr.stNrAttr.enCompressMode = COMPRESS_MODE_FRAME;
    stVpssGrpAttr.stFrameRate.s32SrcFrameRate = -1;
    stVpssGrpAttr.stFrameRate.s32DstFrameRate = -1;

    s32Ret = HI_MPI_VPSS_CreateGrp(VpssGrp, &stVpssGrpAttr);

    if (s32Ret != HI_SUCCESS)
    {
        SAMPLE_PRT("HI_MPI_VPSS_CreateGrp(grp:%d) failed with %#x!\n", VpssGrp, s32Ret);
        return HI_FAILURE;
    }

    return s32Ret;
}

static HI_S32 SAMPLE_VENC_VPSS_DestoryGrp(VPSS_GRP VpssGrp)
{
    HI_S32          s32Ret;

    s32Ret = HI_MPI_VPSS_DestroyGrp(VpssGrp);
    if (s32Ret != HI_SUCCESS)
    {
        SAMPLE_PRT("failed with %#x!\n", s32Ret);
        return HI_FAILURE;
    }

    return s32Ret;
}

static HI_S32 SAMPLE_VENC_VPSS_StartGrp(VPSS_GRP VpssGrp)
{
    HI_S32          s32Ret;

    s32Ret = HI_MPI_VPSS_StartGrp(VpssGrp);
    if (s32Ret != HI_SUCCESS)
    {
        SAMPLE_PRT("HI_MPI_VPSS_CreateGrp(grp:%d) failed with %#x!\n", VpssGrp, s32Ret);
        return HI_FAILURE;
    }

    return s32Ret;
}

static HI_S32 SAMPLE_VENC_VPSS_ChnEnable(VPSS_GRP VpssGrp, VPSS_CHN VpssChn, SAMPLE_VPSS_CHN_ATTR_S *pParam, HI_BOOL bWrapEn)
{
    HI_S32 s32Ret;
    VPSS_CHN_ATTR_S     stVpssChnAttr;
    VPSS_CHN_BUF_WRAP_S stVpssChnBufWrap;

    memset(&stVpssChnAttr, 0, sizeof(VPSS_CHN_ATTR_S));
    stVpssChnAttr.u32Width                     = pParam->stOutPutSize[VpssChn].u32Width;
    stVpssChnAttr.u32Height                    = pParam->stOutPutSize[VpssChn].u32Height;
    stVpssChnAttr.enChnMode                    = VPSS_CHN_MODE_USER;
    stVpssChnAttr.enCompressMode               = pParam->enCompressMode[VpssChn];
    stVpssChnAttr.enDynamicRange               = pParam->enDynamicRange;
    stVpssChnAttr.enPixelFormat                = pParam->enPixelFormat;
    if (stVpssChnAttr.u32Width * stVpssChnAttr.u32Height > 2688 * 1520 ) {
        stVpssChnAttr.stFrameRate.s32SrcFrameRate  = 30;
        stVpssChnAttr.stFrameRate.s32DstFrameRate  = 20;
    } else {
        stVpssChnAttr.stFrameRate.s32SrcFrameRate  = pParam->stFrameRate[VpssChn].s32SrcFrameRate;
        stVpssChnAttr.stFrameRate.s32DstFrameRate  = pParam->stFrameRate[VpssChn].s32DstFrameRate;
    }
    stVpssChnAttr.u32Depth                     = 1;
    stVpssChnAttr.bMirror                      = pParam->bMirror[VpssChn];
    stVpssChnAttr.bFlip                        = pParam->bFlip[VpssChn];
    stVpssChnAttr.enVideoFormat                = VIDEO_FORMAT_LINEAR;
    stVpssChnAttr.stAspectRatio.enMode         = ASPECT_RATIO_NONE;

    s32Ret = HI_MPI_VPSS_SetChnAttr(VpssGrp, VpssChn, &stVpssChnAttr);
    if (s32Ret != HI_SUCCESS)
    {
        SAMPLE_PRT("HI_MPI_VPSS_SetChnAttr chan %d failed with %#x\n", VpssChn, s32Ret);
        goto exit0;
    }

    if (bWrapEn)
    {
        if (VpssChn != 0)   //vpss limit! just vpss chan0 support wrap
        {
            SAMPLE_PRT("Error:Just vpss chan 0 support wrap! Current chan %d\n", VpssChn);
            goto exit0;
        }


        HI_U32 WrapBufLen = 0;
        VPSS_VENC_WRAP_PARAM_S WrapParam;

        memset(&WrapParam, 0, sizeof(VPSS_VENC_WRAP_PARAM_S));
        WrapParam.bAllOnline      = (pParam->ViVpssMode == VI_ONLINE_VPSS_ONLINE) ? 1 : 0;
        WrapParam.u32FrameRate    = GetFrameRateFromSensorType(pParam->enSnsType);
        WrapParam.u32FullLinesStd = GetFullLinesStdFromSensorType(pParam->enSnsType);
        WrapParam.stLargeStreamSize.u32Width = pParam->stOutPutSize[pParam->BigStreamId].u32Width;
        WrapParam.stLargeStreamSize.u32Height= pParam->stOutPutSize[pParam->BigStreamId].u32Height;
        WrapParam.stSmallStreamSize.u32Width = pParam->stOutPutSize[pParam->SmallStreamId].u32Width;
        WrapParam.stSmallStreamSize.u32Height= pParam->stOutPutSize[pParam->SmallStreamId].u32Height;

        if (HI_MPI_SYS_GetVPSSVENCWrapBufferLine(&WrapParam, &WrapBufLen) == HI_SUCCESS)
        {
            AdjustWrapBufLineBySnsType(pParam->enSnsType, &WrapBufLen);

            stVpssChnBufWrap.u32WrapBufferSize = VPSS_GetWrapBufferSize(WrapParam.stLargeStreamSize.u32Width,
                WrapParam.stLargeStreamSize.u32Height, WrapBufLen, pParam->enPixelFormat, DATA_BITWIDTH_8,
                COMPRESS_MODE_NONE, DEFAULT_ALIGN);
            stVpssChnBufWrap.bEnable = 1;
            stVpssChnBufWrap.u32BufLine = WrapBufLen;
            s32Ret = HI_MPI_VPSS_SetChnBufWrapAttr(VpssGrp, VpssChn, &stVpssChnBufWrap);
            if (s32Ret != HI_SUCCESS)
            {
                SAMPLE_PRT("HI_MPI_VPSS_SetChnBufWrapAttr Chn %d failed with %#x\n", VpssChn, s32Ret);
                goto exit0;
            }
        }
        else
        {
            SAMPLE_PRT("Current sensor type: %d, not support BigStream(%dx%d) and SmallStream(%dx%d) Ring!!\n",
                pParam->enSnsType,
                pParam->stOutPutSize[pParam->BigStreamId].u32Width, pParam->stOutPutSize[pParam->BigStreamId].u32Height,
                pParam->stOutPutSize[pParam->SmallStreamId].u32Width, pParam->stOutPutSize[pParam->SmallStreamId].u32Height);
        }

    }

    s32Ret = HI_MPI_VPSS_EnableChn(VpssGrp, VpssChn);
    if (s32Ret != HI_SUCCESS)
    {
        SAMPLE_PRT("HI_MPI_VPSS_EnableChn (%d) failed with %#x\n", VpssChn, s32Ret);
        goto exit0;
    }

exit0:
    return s32Ret;
}

static HI_S32 SAMPLE_VENC_VPSS_ChnDisable(VPSS_GRP VpssGrp, VPSS_CHN VpssChn)
{
    HI_S32 s32Ret;

    s32Ret = HI_MPI_VPSS_DisableChn(VpssGrp, VpssChn);

    if (s32Ret != HI_SUCCESS)
    {
        SAMPLE_PRT("failed with %#x!\n", s32Ret);
        return HI_FAILURE;
    }

    return s32Ret;
}

static HI_S32 SAMPLE_VENC_VPSS_Init(VPSS_GRP VpssGrp, SAMPLE_VPSS_CHN_ATTR_S *pstParam)
{
    HI_S32 i,j;
    HI_S32 s32Ret;
    HI_BOOL bWrapEn;

    s32Ret = SAMPLE_VENC_VPSS_CreateGrp(VpssGrp, pstParam);
    if (s32Ret != HI_SUCCESS)
    {
        goto exit0;
    }

    for (i = 0; i < VPSS_MAX_PHY_CHN_NUM; i++)
    {
        if (pstParam->bChnEnable[i] == HI_TRUE)
        {
            bWrapEn = (i==0)? pstParam->bWrapEn : 0;

            s32Ret = SAMPLE_VENC_VPSS_ChnEnable(VpssGrp, i, pstParam, bWrapEn);
            if (s32Ret != HI_SUCCESS)
            {
                goto exit1;
            }
        }
    }

    i--; // for abnormal case 'exit1' prossess;

    s32Ret = SAMPLE_VENC_VPSS_StartGrp(VpssGrp);
    if (s32Ret != HI_SUCCESS)
    {
        goto exit1;
    }

    return s32Ret;

exit1:
    for (j = 0; j <= i; j++)
    {
        if (pstParam->bChnEnable[j] == HI_TRUE)
        {
            SAMPLE_VENC_VPSS_ChnDisable(VpssGrp, i);
        }
    }

    SAMPLE_VENC_VPSS_DestoryGrp(VpssGrp);
exit0:
    return s32Ret;
}

static HI_VOID SAMPLE_VENC_GetCommVbAttr(const SAMPLE_SNS_TYPE_E enSnsType, const SAMPLE_VPSS_CHN_ATTR_S *pstParam,
    HI_BOOL bSupportDcf, SAMPLE_VB_ATTR_S * pstcommVbAttr)
{
    if (pstParam->ViVpssMode != VI_ONLINE_VPSS_ONLINE)
    {
        SIZE_S snsSize = {0};
        GetSensorResolution(enSnsType, &snsSize);

        if (pstParam->ViVpssMode == VI_OFFLINE_VPSS_ONLINE || pstParam->ViVpssMode == VI_OFFLINE_VPSS_OFFLINE)
        {
            pstcommVbAttr->blkSize[pstcommVbAttr->validNum] = VI_GetRawBufferSize(snsSize.u32Width, snsSize.u32Height,
                                                                                  PIXEL_FORMAT_RGB_BAYER_12BPP,
                                                                                  COMPRESS_MODE_NONE,
                                                                                  DEFAULT_ALIGN);
            pstcommVbAttr->blkCnt[pstcommVbAttr->validNum]  = 3;
            pstcommVbAttr->validNum++;
        }

        if (pstParam->ViVpssMode == VI_OFFLINE_VPSS_OFFLINE)
        {
            pstcommVbAttr->blkSize[pstcommVbAttr->validNum] = COMMON_GetPicBufferSize(snsSize.u32Width, snsSize.u32Height,
                                                                                      PIXEL_FORMAT_YVU_SEMIPLANAR_420,
                                                                                      DATA_BITWIDTH_8,
                                                                                      COMPRESS_MODE_NONE,
                                                                                      DEFAULT_ALIGN);
            pstcommVbAttr->blkCnt[pstcommVbAttr->validNum]  = 2;
            pstcommVbAttr->validNum++;
        }

        if (pstParam->ViVpssMode == VI_ONLINE_VPSS_OFFLINE)
        {
            pstcommVbAttr->blkSize[pstcommVbAttr->validNum] = COMMON_GetPicBufferSize(snsSize.u32Width, snsSize.u32Height,
                                                                                      PIXEL_FORMAT_YVU_SEMIPLANAR_420,
                                                                                      DATA_BITWIDTH_8,
                                                                                      COMPRESS_MODE_NONE,
                                                                                      DEFAULT_ALIGN);
            pstcommVbAttr->blkCnt[pstcommVbAttr->validNum]  = 3;
            pstcommVbAttr->validNum++;

        }
    }
    if(HI_TRUE == pstParam->bWrapEn)
    {
        pstcommVbAttr->blkSize[pstcommVbAttr->validNum] = VPSS_GetWrapBufferSize(pstParam->stOutPutSize[pstParam->BigStreamId].u32Width,
                                                                                 pstParam->stOutPutSize[pstParam->BigStreamId].u32Height,
                                                                                 pstParam->WrapBufLine,
                                                                                 pstParam->enPixelFormat,DATA_BITWIDTH_8,COMPRESS_MODE_NONE,DEFAULT_ALIGN);
        pstcommVbAttr->blkCnt[pstcommVbAttr->validNum]  = 1;
        pstcommVbAttr->validNum++;
    }
    else
    {
        pstcommVbAttr->blkSize[pstcommVbAttr->validNum] = COMMON_GetPicBufferSize(pstParam->stOutPutSize[0].u32Width, pstParam->stOutPutSize[0].u32Height,
                                                                                  pstParam->enPixelFormat,
                                                                                  DATA_BITWIDTH_8,
                                                                                  pstParam->enCompressMode[0],
                                                                                  DEFAULT_ALIGN);

        if (pstParam->ViVpssMode == VI_ONLINE_VPSS_ONLINE)
        {
            pstcommVbAttr->blkCnt[pstcommVbAttr->validNum]  = 3;
        }
        else
        {
            pstcommVbAttr->blkCnt[pstcommVbAttr->validNum]  = 2;
        }

        pstcommVbAttr->validNum++;
    }



    pstcommVbAttr->blkSize[pstcommVbAttr->validNum] = COMMON_GetPicBufferSize(pstParam->stOutPutSize[1].u32Width, pstParam->stOutPutSize[1].u32Height,
                                                                              pstParam->enPixelFormat,
                                                                              DATA_BITWIDTH_8,
                                                                              pstParam->enCompressMode[1],
                                                                              DEFAULT_ALIGN);

    if (pstParam->ViVpssMode == VI_ONLINE_VPSS_ONLINE)
    {
        pstcommVbAttr->blkCnt[pstcommVbAttr->validNum]  = 3;
    }
    else
    {
        pstcommVbAttr->blkCnt[pstcommVbAttr->validNum]  = 2;
    }
    pstcommVbAttr->validNum++;


    //vgs dcf use
    if(HI_TRUE == bSupportDcf)
    {
        pstcommVbAttr->blkSize[pstcommVbAttr->validNum] = COMMON_GetPicBufferSize(160, 120,
                                                                                  pstParam->enPixelFormat,
                                                                                  DATA_BITWIDTH_8,
                                                                                  COMPRESS_MODE_NONE,
                                                                                  DEFAULT_ALIGN);
        pstcommVbAttr->blkCnt[pstcommVbAttr->validNum]  = 1;
        pstcommVbAttr->validNum++;
    }

}

HI_S32 SAMPLE_VENC_CheckSensor(SAMPLE_SNS_TYPE_E   enSnsType,SIZE_S  stSize)
{
    HI_S32 s32Ret;
    SIZE_S          stSnsSize;
    PIC_SIZE_E      enSnsSize;

    s32Ret = SAMPLE_COMM_VI_GetSizeBySensor(enSnsType, &enSnsSize);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("SAMPLE_COMM_VI_GetSizeBySensor failed!\n");
        return s32Ret;
    }
    s32Ret = SAMPLE_COMM_SYS_GetPicSize(enSnsSize, &stSnsSize);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("SAMPLE_COMM_SYS_GetPicSize failed!\n");
        return s32Ret;
    }

    if((stSnsSize.u32Width < stSize.u32Width) || (stSnsSize.u32Height < stSize.u32Height))
    {
        //SAMPLE_PRT("Sensor size is (%d,%d), but encode chnl is (%d,%d) !\n",
            //stSnsSize.u32Width,stSnsSize.u32Height,stSize.u32Width,stSize.u32Height);
        return HI_FAILURE;
    }

    return HI_SUCCESS;
}

HI_S32 SAMPLE_VENC_ModifyResolution(SAMPLE_SNS_TYPE_E   enSnsType,PIC_SIZE_E *penSize,SIZE_S *pstSize)
{
    HI_S32 s32Ret;
    SIZE_S          stSnsSize;
    PIC_SIZE_E      enSnsSize;

    s32Ret = SAMPLE_COMM_VI_GetSizeBySensor(enSnsType, &enSnsSize);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("SAMPLE_COMM_VI_GetSizeBySensor failed!\n");
        return s32Ret;
    }
    s32Ret = SAMPLE_COMM_SYS_GetPicSize(enSnsSize, &stSnsSize);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("SAMPLE_COMM_SYS_GetPicSize failed!\n");
        return s32Ret;
    }

    *penSize = enSnsSize;
    pstSize->u32Width  = stSnsSize.u32Width;
    pstSize->u32Height = stSnsSize.u32Height;

    return HI_SUCCESS;
}

/******************************************************************************
* funciton : get stream from each channels and save them
******************************************************************************/
HI_VOID* VENC_GetVencStreamProc(HI_VOID *p)
{
    HI_S32 i, j;
    HI_S32 s32ChnTotal;
    VENC_CHN_ATTR_S stVencChnAttr;
    hiSAMPLE_VENC_GETSTREAM_RTSP_PARA_S* pstPara;
    HI_S32 maxfd = 0;
    struct timeval TimeoutVal;
    fd_set read_fds;
    HI_U32 u32PictureCnt[VENC_MAX_CHN_NUM]={0};
    HI_S32 VencFd[VENC_MAX_CHN_NUM];
    HI_S32 VpssFd[VENC_MAX_CHN_NUM];
    HI_CHAR aszFileName[VENC_MAX_CHN_NUM][64];
    FILE* pFile[VENC_MAX_CHN_NUM];
    char szFilePostfix[10];
    VENC_CHN_STATUS_S stStat;
    VENC_STREAM_S stStream;
    HI_S32 s32Ret;
    VENC_CHN VencChn;
    PAYLOAD_TYPE_E enPayLoadType[VENC_MAX_CHN_NUM];
    VENC_STREAM_BUF_INFO_S stStreamBufInfo[VENC_MAX_CHN_NUM];

    // prctl(PR_SET_NAME, "GetVencStream", 0,0,0);
    unsigned char* pStremData = NULL;
	int nSize = 0;

    pstPara = (hiSAMPLE_VENC_GETSTREAM_RTSP_PARA_S*)p;
    s32ChnTotal = pstPara->s32Cnt;
#ifdef INSERT_SEI_EN
    HI_S32 frameType = 0, flag = 0;
#endif
    HI_U8 polygonSsrc[128] ;
    memcpy(polygonSsrc, "test_sei_info_0715", sizeof(polygonSsrc));

    // MP4Context* ctx = NULL;
    int record_flag = 1;
    /******************************************
     step 1:  check & prepare save-file & venc-fd
    ******************************************/
    if (s32ChnTotal >= VENC_MAX_CHN_NUM)
    {
        SAMPLE_PRT("input count invaild\n");
        return NULL;
    }
    for (i = 0; i < s32ChnTotal; i++)
    {
        /* decide the stream file name, and open file to save stream */
        VencChn = pstPara->VeChn[i];
        s32Ret = HI_MPI_VENC_GetChnAttr(VencChn, &stVencChnAttr);
        if (s32Ret != HI_SUCCESS)
        {
            SAMPLE_PRT("HI_MPI_VENC_GetChnAttr chn[%d] failed with %#x!\n", \
                       VencChn, s32Ret);
            return NULL;
        }
        enPayLoadType[i] = stVencChnAttr.stVencAttr.enType;

        s32Ret = SAMPLE_COMM_VENC_GetFilePostfix(enPayLoadType[i], szFilePostfix);
        if (s32Ret != HI_SUCCESS)
        {
            SAMPLE_PRT("SAMPLE_COMM_VENC_GetFilePostfix [%d] failed with %#x!\n", \
                       stVencChnAttr.stVencAttr.enType, s32Ret);
            return NULL;
        }

        if(PT_JPEG != enPayLoadType[i])
        {
            snprintf(aszFileName[i],32, "stream_chn%d%s", i, szFilePostfix);

            // pFile[i] = fopen(aszFileName[i], "wb");
            // if (!pFile[i])
            // {
            //     SAMPLE_PRT("open file[%s] failed!\n",
            //                aszFileName[i]);
            //     return NULL;
            // }
        }
        /* Set Venc Fd. */
        VpssFd[i] = HI_MPI_VPSS_GetChnFd(pstPara->VpssGrp, pstPara->VpssChn);
        if (VpssFd[i] < 0)
        {
            SAMPLE_PRT("HI_MPI_VPSS_GetChnFd failed with %#x!\n", VpssFd[i]);
            return NULL;
        }
        if (maxfd <= VpssFd[i])
        {
            maxfd = VpssFd[i];
        }

        // VencFd[i] = HI_MPI_VENC_GetFd(VencChn);
        // if (VencFd[i] < 0)
        // {
        //     SAMPLE_PRT("HI_MPI_VENC_GetFd failed with %#x!\n",
        //                VencFd[i]);
        //     return NULL;
        // }
        // if (maxfd <= VencFd[i])
        // {
        //     maxfd = VencFd[i];
        // }

        // s32Ret = HI_MPI_VENC_GetStreamBufInfo (VencChn, &stStreamBufInfo[i]);
        // if (HI_SUCCESS != s32Ret)
        // {
        //     SAMPLE_PRT("HI_MPI_VENC_GetStreamBufInfo failed with %#x!\n", s32Ret);
        //     return (void *)HI_FAILURE;
        // }
    }

    uint8_t naluBuffer[MAX_NALU_SIZE] = {0};
    size_t naluSize = 0;
    uint8_t* sps = NULL, *pps = NULL;
    size_t spsSize = 0, ppsSize = 0;
    VIDEO_FRAME_INFO_S astFrame[25];
    char *point;
    int point_i, send_cnt = 0, set_point_flag = 0, jilu = 0;
    float gap;
    /******************************************
     step 2:  Start to get streams of each channel.
    ******************************************/
    while (HI_TRUE == pstPara->bThreadStart)
    {
        FD_ZERO(&read_fds);
        for (i = 0; i < s32ChnTotal; i++)
        {
            FD_SET(VpssFd[i], &read_fds);
            // FD_SET(VencFd[i], &read_fds);
        }

        TimeoutVal.tv_sec  = 2;
        TimeoutVal.tv_usec = 0;
        s32Ret = select(maxfd + 1, &read_fds, NULL, NULL, &TimeoutVal);
        if (s32Ret < 0)
        {
            SAMPLE_PRT("select failed!\n");
            usleep(100000); // 等待100ms
            continue;
        }
        else if (s32Ret == 0)
        {
            SAMPLE_PRT("get venc stream time out, exit thread\n");
            continue;
        }
        else
        {
            for (i = 0; i < s32ChnTotal; i++)
            {
                // if (FD_ISSET(VencFd[i], &read_fds))
                if (FD_ISSET(VpssFd[i], &read_fds))
                {
                    /*******************************************************
                     step 2.1 : query how many packs in one-frame stream.
                    *******************************************************/
                    memset(&stStream, 0, sizeof(stStream));
                    // printf("pstPara->session=%s,line:%d\n", pstPara->session, __LINE__);

                    VencChn = pstPara->VeChn[i];
                    point = (char*)malloc(sizeof(char)*frame_rate);
                    gap = (float)50/frame_rate;
                    for(point_i = 0; point_i < frame_rate; point_i++) {
                        point[point_i] = -1;
                    }
                    if(frame_rate >= 9 && frame_rate <= 50) {
                        for(point_i = 0; point_i < frame_rate; point_i++) {
                            point[point_i] = point_i*gap;
                        }
                    }else{
                        frame_rate = 25;
                        gap = 2;
                        for(point_i = 0; point_i < frame_rate; point_i++) {
                            point[point_i] = point_i * gap;
                        }
                    }
                #ifdef INSERT_SEI_EN
                    //insert sei info
                    // if(H264E_NALU_SEI == frameType){
                    //     //HI_U8 tmp_src[128] = {0};
                        
                    //     HI_U8  polygonSsrc[] = "{\"camera\":{\"setting\":{\"polygon\":{\"resolution\":[800,450],\"origin\":\"left-top\",\"path\":[[0.00125,0.36083],[0.29625,0.12972]]}}}}";
                    //    // sprintf(tmp_src, "%s->%s:[%d].", au8UserData, __func__ ,__LINE__);
                        
                    //     s32Ret = HI_MPI_VENC_InsertUserData(VencChn, polygonSsrc, sizeof(polygonSsrc));
                    //     if(HI_SUCCESS != s32Ret){
                    //         free(stStream.pstPack);
                    //         stStream.pstPack = NULL;
                    //         SAMPLE_PRT("HI_MPI_VENC_InsertUserData failed with %#x!\n", s32Ret);
                    //         break;
                    //     }
                    //     frameType = 0;
                    // }
                #endif

                    while(send_cnt < 50){
                        // printf("pstPara->session=%s,line:%d,send_cnt=%d\n", pstPara->session, __LINE__,send_cnt);
                        s32Ret = HI_MPI_VPSS_GetChnFrame(pstPara->VpssGrp, pstPara->VpssChn, &astFrame[i], -1);
                        if (HI_SUCCESS != s32Ret)
                        {
                            SAMPLE_PRT("HI_MPI_VPSS_GetChnFrame failed.s32Ret:0x%x !\n", s32Ret);
                             // 添加错误处理
                            if (s32Ret == HI_ERR_VPSS_BUSY) {
                                usleep(10000); // 等待10ms
                                continue;
                            }
                            break;
                        }
                        send_cnt++;
                        astFrame[i].stVFrame.enPixelFormat =    PIXEL_FORMAT_YVU_SEMIPLANAR_420;
                        if(point[jilu] == send_cnt-1) {
                            //printf("venc send data\n");
                            HI_MPI_VENC_SendFrame(VencChn, &astFrame[i], -1);
                            jilu++;
                        }

                        // 处理完成后释放资源
                        if (astFrame[i].stVFrame.u64PhyAddr[0] != 0) {
                            HI_MPI_VPSS_ReleaseChnFrame(pstPara->VpssGrp, pstPara->VpssChn, &astFrame[i]);
                        }
                        
                        s32Ret = HI_MPI_VENC_QueryStatus(VencChn, &stStat);
                        if (HI_SUCCESS != s32Ret)
                        {
                            SAMPLE_PRT("HI_MPI_VENC_QueryStatus chn[%d] failed with %#x!\n", VencChn, s32Ret);
                            break;
                        }

                        /*******************************************************
                        step 2.2 :suggest to check both u32CurPacks and u32LeftStreamFrames at the same time,for example:
                        if(0 == stStat.u32CurPacks || 0 == stStat.u32LeftStreamFrames)
                        {
                            SAMPLE_PRT("NOTE: Current  frame is NULL!\n");
                            continue;
                        }
                        *******************************************************/
                        if(0 == stStat.u32CurPacks)
                        {
                            SAMPLE_PRT("NOTE: Current  frame is NULL!\n");
                            continue;
                        }
                        /*******************************************************
                         step 2.3 : malloc corresponding number of pack nodes.
                        *******************************************************/
                        stStream.pstPack = (VENC_PACK_S*)malloc(sizeof(VENC_PACK_S) * stStat.u32CurPacks);
                        if (NULL == stStream.pstPack)
                        {
                            SAMPLE_PRT("malloc stream pack failed!\n");
                            break;
                        }


                        /*******************************************************
                         step 2.4 : call mpi to get one-frame stream
                        *******************************************************/

                        stStream.u32PackCount = stStat.u32CurPacks;
                        s32Ret = HI_MPI_VENC_GetStream(VencChn, &stStream, HI_TRUE);
                        if (HI_SUCCESS != s32Ret)
                        {
                            free(stStream.pstPack);
                            stStream.pstPack = NULL;
                            SAMPLE_PRT("HI_MPI_VENC_GetStream failed with %#x!\n", \
                                    s32Ret);
                            break;
                        }

                        /*******************************************************
                         step 2.5 : save frame to file
                        *******************************************************/
                        if(PT_JPEG == enPayLoadType[i])
                        {
                            strcpy(szFilePostfix, ".jpg");
                            snprintf(aszFileName[i],32, "stream_chn%d_%d%s", VencChn, u32PictureCnt[i],szFilePostfix);
                            pFile[i] = fopen(aszFileName[i], "wb");
                            if (!pFile[i])
                            {
                                SAMPLE_PRT("open file err!\n");
                                return NULL;
                            }
                        }

                        for (j = 0; j < stStream.u32PackCount; j++)
                        {
                            pStremData = (unsigned char*)stStream.pstPack[j].pu8Addr+stStream.pstPack[j].u32Offset;
                            nSize = stStream.pstPack[j].u32Len-stStream.pstPack[j].u32Offset;
                            //录像
                            if (process_and_push_frame(pStremData, nSize, stStream.pstPack[j].u64PTS) != 0) {
                                printf("Main loop: Failed to process/push frame. Stopping simulation.\n");
                                break;
                            }
                            
                            // printf("nSize=%d, enH264EType=%d\n", nSize, stStream.pstPack[j].DataType.enH264EType);
                            //rtsp
                            #ifdef RTSP_RECORD
                                RtspServerPushStreamInfo info = {0};
                                info.chn = 1;
                                info.stream_type = RTSP_SERVER_STREAMING_MAIN;
                                info.buff = pStremData ;
                                info.size = nSize;
                                info.pts = -1;
                                RtspServerPushStream(&info);
                            #else
                                if(pstPara->gRtsplive && pstPara->session)
                                {   
                                    // printf("nSize=%d,[%02x %02x %02x %02x %02x %02x %02x ]\n", nSize, pStremData[0],pStremData[1],pStremData[2],pStremData[3],pStremData[4],pStremData[5],pStremData[6]);           
                                    s32Ret = rtsp_sever_tx_video(pstPara->gRtsplive, pstPara->session, pStremData, nSize, stStream.pstPack[j].u64PTS);
                                    // printf("pstPara->session=%s\n", pstPara->session);
                                }
                            #endif
                        }	

                        /*******************************************************
                         step 2.6 : release stream
                        *******************************************************/
                        s32Ret = HI_MPI_VENC_ReleaseStream(VencChn, &stStream);
                        if (HI_SUCCESS != s32Ret)
                        {
                            SAMPLE_PRT("HI_MPI_VENC_ReleaseStream failed!\n");
                            free(stStream.pstPack);
                            stStream.pstPack = NULL;
                            break;
                        }

                        /*******************************************************
                         step 2.7 : free pack nodes
                        *******************************************************/
                        free(stStream.pstPack);
                        stStream.pstPack = NULL;
                        u32PictureCnt[i]++;
                        if(PT_JPEG == enPayLoadType[i])
                        {
                            fclose(pFile[i]);
                        }
                    }
                    free(point);
                    send_cnt = 0;
                    jilu = 0;
                }
            }
        }
    }
    /*******************************************************
    * step 3 : close save-file
    *******************************************************/
    for (i = 0; i < s32ChnTotal; i++)
    {
        if(PT_JPEG != enPayLoadType[i])
        {
            fclose(pFile[i]);
        }
    }
    return NULL;
}


void save_frame(const VIDEO_FRAME_S *pstVideoFrame, const char *filename) {
    FILE *pFile = fopen(filename, "wb");
    if (!pFile) {
        perror("Failed to open file");
        return;
    }

    for (HI_U32 i = 0; i < pstVideoFrame->u32Height; i++) {
        fwrite((void *)pstVideoFrame->u64VirAddr[0] + i * pstVideoFrame->u32Width, 1, pstVideoFrame->u32Width, pFile);
    }

    if (pstVideoFrame->enPixelFormat == PIXEL_FORMAT_YVU_SEMIPLANAR_420) {
        for (HI_U32 i = 0; i < pstVideoFrame->u32Height / 2; i++) {
            fwrite((void *)pstVideoFrame->u64VirAddr[1] + i * pstVideoFrame->u32Width, 1, pstVideoFrame->u32Width, pFile);
        }
    }
    else if(pstVideoFrame->enPixelFormat == PIXEL_FORMAT_YVU_SEMIPLANAR_422){
        for (HI_U32 i = 0; i < pstVideoFrame->u32Height; i++) {
            fwrite((void *)pstVideoFrame->u64VirAddr[1] + i * pstVideoFrame->u32Width, 1, pstVideoFrame->u32Width, pFile);
        }
    }

    fclose(pFile);
}


// static HI_VOID *GET_FRAME_FROM_VPSS(HI_VOID *pArgs)
// {
//     HI_S32 s32Ret;
//     VIDEO_FRAME_INFO_S astFrame[2];
//     // VIDEO_FRAME_INFO_S stExtFrmInfo;
//     HI_S32 s32MilliSec = 2000;
//     HI_S32 s32VpssGrp = 0;
//     HI_S32 as32VpssChn[] = {0, 1};
//     HI_U32 remainUVSize = 0;
//     int number = 0;
//     int capture = 0;
//     while (1){

//         if(capture == 1){
//             s32Ret = HI_MPI_VPSS_GetChnFrame(s32VpssGrp, as32VpssChn[1], &astFrame[0], s32MilliSec);
//             if (HI_SUCCESS != s32Ret){
//                 err("HI_MPI_VPSS_GetChnFrame false 0");
//                 usleep(10);
//                 continue;
//             }

//             // HI_U8  *yuvBuffer = NULL;
//             info("pstVideoFrame->u32Stride[0]:%u, pstVideoFrame->u32Stride[1]:%u, u32Width[1]:%u, u32Height:%u\n",astFrame[0].stVFrame.u32Stride[0] ,astFrame[0].stVFrame.u32Stride[1] ,astFrame[0].stVFrame.u32Width , astFrame[0].stVFrame.u32Height);

//             if(astFrame[0].stVFrame.enPixelFormat == PIXEL_FORMAT_YVU_SEMIPLANAR_422)
//             {
//                 //length
//                 remainUVSize = astFrame[0].stVFrame.u32Width * astFrame[0].stVFrame.u32Height;
//                 // yuvBuffer = (HI_U8 *) malloc(astFrame[0].stVFrame.u32Width * astFrame[0].stVFrame.u32Height * 2);
//             }
//             else if(astFrame[0].stVFrame.enPixelFormat == PIXEL_FORMAT_YVU_SEMIPLANAR_420)
//             {
//                 //size
//                 remainUVSize = astFrame[0].stVFrame.u32Width * astFrame[0].stVFrame.u32Height / 2;
//                 // yuvBuffer = (HI_U8 *) malloc(astFrame[0].stVFrame.u32Width * astFrame[0].stVFrame.u32Height * 3 /2);
//             }
//             else
//             {
//                 remainUVSize = astFrame[0].stVFrame.u32Width  * astFrame[0].stVFrame.u32Height / 2;
//                 // yuvBuffer = (HI_U8 *) malloc(astFrame[0].stVFrame.u32Width * astFrame[0].stVFrame.u32Height * 3 /2);
//                 err("Current mode is not support!\n");
//             }

//             // astFrame[0].stVFrame.u64VirAddr[0] 
//             HI_U8 *pU8addr = HI_MPI_SYS_Mmap(astFrame[0].stVFrame.u64PhyAddr[0], astFrame[0].stVFrame.u32Width * astFrame[0].stVFrame.u32Height + remainUVSize);
//             if (pU8addr == NULL) {
//                 err("HI_MPI_SYS_Mmap failed\n");
//                 goto BASE_RELEASE;
//             }

//             if(0 == number){
//                 // save_frame(&(astFrame[0].stVFrame), "/nfs/vpss.yuv");
//                 FILE *pFile = fopen("./vpss.yuv", "wb");
//                 if (!pFile) {
//                     err("Failed to open file");
//                     continue;;
//                 }

//                 fwrite((void *)pU8addr , astFrame[0].stVFrame.u32Width * astFrame[0].stVFrame.u32Height + remainUVSize, 1, pFile);
//                 fclose(pFile);
//             }
                
//             number++;
//             info("---->%d\n", number);
//             // if (getQueueLen() < FRAME_QUEUE_SIZE){      	
//             //     int ret = WriteQueue(pU8addr, astFrame[0].stVFrame.u32Width * astFrame[0].stVFrame.u32Height + remainUVSize);	
//             //     warn("ret=%d\n",ret);
//             // }

//             // 释放映射的内存
//             HI_MPI_SYS_Munmap(pU8addr, astFrame[0].stVFrame.u32Width * astFrame[0].stVFrame.u32Height + remainUVSize);
//             // HI_MPI_SYS_Munmap(astFrame[0].stVFrame.u64VirAddr[1], remainUVSize);
        
//         BASE_RELEASE:
//             s32Ret = HI_MPI_VPSS_ReleaseChnFrame(s32VpssGrp, as32VpssChn[0], &astFrame[0]);
//             if (HI_SUCCESS != s32Ret){
//                 SAMPLE_PRT("Error(%#x),HI_MPI_VPSS_ReleaseChnFrame failed,Grp(%d) chn(%d)!\n",s32Ret, s32VpssGrp, as32VpssChn[0]);
//             }
//         }
//         usleep(10);
//         capture = 0;
//     }
//     return HI_NULL;
// }

HI_S32 VIO_VIchn_frame_Save(VIDEO_FRAME_INFO_S          *astFrame, int cnt)
{
    // int                    i, j;
    HI_S32                  s32Ret;
    // HI_S32                 s32MilliSec = 4000;
    // HI_U32                 u32CapCnt = 0;
    // HI_S32                  s32DumpCnt = 0;

    // ISP_MESH_SHADING_TABLE_S  stIspMLSCTable;
    FILE       *pfile = NULL;
    HI_CHAR     name[128] = {0};
    HI_U32      u32Width;
    HI_U32      u32Height;
    HI_U32      u32BitWidth;

    /* dump file */
    u32Width    = astFrame[0].stVFrame.u32Width;
    u32Height   = astFrame[0].stVFrame.u32Height;
    u32BitWidth = 8;//SAMPLE_COMM_VI_PixelFormat2BitWidth(astFrame[0].stVFrame.enPixelFormat);

    snprintf(name, sizeof(name), "/nfs/vi_chn_w%d_h%d_%d.yuv", u32Width, u32Height, cnt);//, u32BitWidth, 
        //SAMPLE_COMM_VI_CompressMode2String(astFrame[0].stVFrame.enCompressMode));
    pfile = fopen(name, "wb");
    if (NULL == pfile)
    {
        SAMPLE_PRT("open file %s fail !\n", name);
        return HI_NULL;
    }

    /* save VI frame to file */
    // saveViChnFrameToFile(&astFrame[0].stVFrame, pfile);
    // VIO_Frame_svFile(ViPipe, &astFrame[0].stVFrame, u32MeshScale, u32ByteAlign, &stIspMLSCTable);

    s32Ret = SAMPLE_COMM_VI_SaveRaw(&astFrame[0].stVFrame, u32BitWidth, pfile);

    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("SAMPLE_COMM_VI_SaveRaw failed with %#x!\n", s32Ret);
        goto end;
    }

end:
    if (pfile) {
        fclose(pfile);
        pfile = HI_NULL;
    }
    fprintf(stderr, "save done, s32Ret = [%d] ------Done!\n", s32Ret);

    return HI_SUCCESS;
}

void *CONFIG_VO_START(void *arg){
    
    SAMPLE_VO_CONFIG_S *stVoConfig = (SAMPLE_VO_CONFIG_S *)arg;
    while(1)
    {
        if(otherPreview.cvbs == 1){
            printf("start SAMPLE_COMM_VPSS_Bind_VO!\n");
            SAMPLE_COMM_VO_StartChn(0, 0);
            SAMPLE_COMM_VPSS_Bind_VO(0, 1, 0, 0);
            // SAMPLE_COMM_VI_Bind_VO(0, 0, 0, 0);
            otherPreview.cvbs = -1;
        }else if(otherPreview.cvbs == 0){
            printf("close vo!\n");
            SAMPLE_COMM_VPSS_UnBind_VO(0, 1, 0, 0);
            HI_MPI_VO_DisableChn(0, 0);
            // SAMPLE_COMM_VI_UnBind_VO(0, 0, 0, 0);
            otherPreview.cvbs = -1;
        }

        usleep(1000);
    }
  
}
/******************************************************************************
* function: H.265e + H264e@720P, H.265 Channel resolution adaptable with sensor
******************************************************************************/
void *SAMPLE_VENC_1080P_CLASSIC(void *p)
//HI_S32 SAMPLE_VENC_H265_H264(void)
{
    HI_S32 i;
    HI_S32 s32Ret;
    SIZE_S          stSize[2];
    PIC_SIZE_E      enSize[2]     = {BIG_STREAM_SIZE_IMX335, SMALL_STREAM_SIZE};
    HI_S32          s32ChnNum     = 1;
    VENC_CHN        VencChn[2]    = {1,1};
    HI_U32          u32Profile[2] = {0,2};
    PAYLOAD_TYPE_E  enPayLoad[2]  = {PT_H264, PT_H264};
    VENC_GOP_MODE_E enGopMode;
    VENC_GOP_ATTR_S stGopAttr;
    SAMPLE_RC_E     enRcMode;
    HI_BOOL         bRcnRefShareBuf = HI_TRUE;

    VI_DEV          ViDev        = 0;
    VI_PIPE         ViPipe       = 0;
    VI_CHN          ViChn        = 0;
    SAMPLE_VI_CONFIG_S stViConfig;

    VPSS_GRP        VpssGrp        = 0;
    VPSS_CHN        VpssChn[2]     = {0,1};
    HI_BOOL         abChnEnable[VPSS_MAX_PHY_CHN_NUM] = {1,1,0};
    SAMPLE_VPSS_CHN_ATTR_S stParam;
    SAMPLE_VB_ATTR_S commVbAttr;
    VIDEO_FRAME_INFO_S astFrame[2];
    SAMPLE_VO_CONFIG_S stVoConfig;
    VO_CHN          VoChn          = 0;

    passing_para *param = (passing_para *)p;

    hiSAMPLE_VENC_GETSTREAM_RTSP_PARA_S * pstPara = (hiSAMPLE_VENC_GETSTREAM_RTSP_PARA_S *)malloc(sizeof(hiSAMPLE_VENC_GETSTREAM_RTSP_PARA_S));

    SAMPLE_COMM_VI_GetSensorInfo(&stViConfig);
    if(SAMPLE_SNS_TYPE_BUTT == stViConfig.astViInfo[0].stSnsInfo.enSnsType)
    {
        SAMPLE_PRT("Not set SENSOR%d_TYPE !\n",0);
        return HI_FAILURE;
    }

    if(stViConfig.astViInfo[0].stSnsInfo.enSnsType == SONY_IMX335_MIPI_4M_30FPS_12BIT)
    {
        enSize[0] = BIG_STREAM_SIZE_IMX335;
    }
    else if(stViConfig.astViInfo[0].stSnsInfo.enSnsType == BT656_2M_30FPS_8BIT)
    {
        enSize[0] = BIG_STREAM_SIZE_BT656;
    }

    for(i=0; i<2; i++)
    {
        s32Ret = SAMPLE_COMM_SYS_GetPicSize(enSize[i], &stSize[i]);
        if (HI_SUCCESS != s32Ret)
        {
            SAMPLE_PRT("SAMPLE_COMM_SYS_GetPicSize failed!\n");
            return s32Ret;
        }
    }
    
    s32Ret = SAMPLE_VENC_CheckSensor(stViConfig.astViInfo[0].stSnsInfo.enSnsType,stSize[0]);
    if(s32Ret != HI_SUCCESS)
    {
        s32Ret = SAMPLE_VENC_ModifyResolution(stViConfig.astViInfo[0].stSnsInfo.enSnsType,&enSize[0],&stSize[0]);
        if(s32Ret != HI_SUCCESS)
        {
            return HI_FAILURE;
        }
    }

    SAMPLE_VENC_GetDefaultVpssAttr(stViConfig.astViInfo[0].stSnsInfo.enSnsType, abChnEnable, stSize, &stParam);

    /******************************************
      step 1: init sys alloc common vb
    ******************************************/
    memset(&commVbAttr, 0, sizeof(commVbAttr));
    commVbAttr.supplementConfig = HI_FALSE;
    SAMPLE_VENC_GetCommVbAttr(stViConfig.astViInfo[0].stSnsInfo.enSnsType, &stParam, HI_FALSE, &commVbAttr);

    s32Ret = SAMPLE_VENC_SYS_Init(&commVbAttr);
    if(s32Ret != HI_SUCCESS)
    {
        SAMPLE_PRT("Init SYS err for %#x!\n", s32Ret);
        return s32Ret;
    }
    
#ifdef AUDIO_EN
    *(param->sys_init_statu) = 1;//tell audio init completed
#endif

    stViConfig.s32WorkingViNum       = 1;
    stViConfig.astViInfo[0].stDevInfo.ViDev     = ViDev;
    stViConfig.astViInfo[0].stPipeInfo.aPipe[0] = ViPipe;
    stViConfig.astViInfo[0].stChnInfo.ViChn     = ViChn;
    stViConfig.astViInfo[0].stChnInfo.enDynamicRange = DYNAMIC_RANGE_SDR8;
    stViConfig.astViInfo[0].stChnInfo.enPixFormat    = PIXEL_FORMAT_YVU_SEMIPLANAR_420;

    s32Ret = SAMPLE_VENC_VI_Init(&stViConfig, stParam.ViVpssMode);
    if(s32Ret != HI_SUCCESS)
    {
        SAMPLE_PRT("Init VI err for %#x!\n", s32Ret);
        return HI_FAILURE;
    }

#ifdef SET_PIPE_FRAME_SOURCE
    VI_PIPE_FRAME_SOURCE_E pipe_source = 100;
    s32Ret = HI_MPI_VI_GetPipeFrameSource(ViPipe, &pipe_source);
    if (s32Ret != HI_SUCCESS)
    {
        printf("HI_MPI_VI_GetPipeFrameSource failed with error code: %#x\n", s32Ret);
        return NULL;
    }
    printf("HI_MPI_VI_GetPipeFrameSource: %d\n", pipe_source);

    s32Ret = GK_API_VI_SetPipeFrameSource(ViPipe, VI_PIPE_FRAME_SOURCE_USER_BE);
    if (s32Ret != HI_SUCCESS)
    {
        printf("GK_API_VI_SetPipeFrameSource failed with error code: %#x\n", s32Ret);
        return NULL;
    }
   #endif
    
    s32Ret = SAMPLE_VENC_VPSS_Init(VpssGrp,&stParam);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("Init VPSS err for %#x!\n", s32Ret);
        goto EXIT_VI_STOP;
    }
    
    s32Ret = SAMPLE_COMM_VI_Bind_VPSS(ViPipe, ViChn, VpssGrp);
    if(s32Ret != HI_SUCCESS)
    {
        SAMPLE_PRT("VI Bind VPSS err for %#x!\n", s32Ret);
        goto EXIT_VPSS_STOP;
    }

#ifdef VI_LOW_DELAY
    //set vi LOW_DELAY
    VI_LOW_DELAY_INFO_S viLowDelayInfo;
    memset(&viLowDelayInfo, 0x0, sizeof(viLowDelayInfo));
    s32Ret = HI_MPI_VI_GetChnLowDelayAttr(ViPipe, ViChn, &viLowDelayInfo);
    if(s32Ret != HI_SUCCESS)
    {
        SAMPLE_PRT("HI_MPI_VI_GetChnLowDelayAttr failed for %#x!\n", s32Ret);
        return HI_FAILURE;
    }

    viLowDelayInfo.bEnable = HI_TRUE;
    viLowDelayInfo.u32LineCnt = 128;
    s32Ret = HI_MPI_VI_SetChnLowDelayAttr(ViPipe, ViChn, &viLowDelayInfo);
    if(s32Ret != HI_SUCCESS)
    {
        SAMPLE_PRT("HI_MPI_VI_SetChnLowDelayAttr failed %#x!\n", s32Ret);
        return HI_FAILURE;
    }
#endif
   
#ifdef GET_ONE_FRAME_FROM_VI
    s32Ret = HI_MPI_VI_GetChnFrame(ViPipe, ViChn, &astFrame[0], 4000);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("HI_MPI_VI_GetChnFrame() failed. s32Ret: 0x%x !\n", s32Ret);
    }
    else {
        SAMPLE_PRT("HI_MPI_VI_GetChnFrame() done. s32Ret: [0x%x] !\n", s32Ret);
        VIO_VIchn_frame_Save(&astFrame[0], 0);
        s32Ret = HI_MPI_VI_ReleaseChnFrame(ViPipe, ViChn, &astFrame[0]);
    }
#endif

    // pthread_t thread ;
    // if (pthread_create(&thread, NULL, GET_FRAME_FROM_VPSS, NULL) != 0) {
    //     perror("Failed to create thread");
    //      goto EXIT_VI_VPSS_UNBIND;
    // }else{
    //     SAMPLE_PRT("Start vpss_capture_thread Thread.\n");
    // }
   /******************************************
    start stream venc
    ******************************************/

    enRcMode = SAMPLE_VENC_GetRcMode();

    enGopMode = SAMPLE_VENC_GetGopMode();
    s32Ret = SAMPLE_COMM_VENC_GetGopAttr(enGopMode,&stGopAttr);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("Venc Get GopAttr for %#x!\n", s32Ret);
        goto EXIT_VI_VPSS_UNBIND;
    }

    // otherPreview.cvbs = 1;
#ifdef CVBS_EN
    /**********VO CONFIG ********/
    SAMPLE_PRT("VO CONFIG....!11!!!!.......\n");
    SAMPLE_PRT("VPSS_MAX_PHY_CHN_NUM = %d\n", VPSS_MAX_PHY_CHN_NUM);
    SAMPLE_COMM_VO_GetDefConfig(&stVoConfig);
    stVoConfig.enVoIntfType = VO_INTF_BT656;
    stVoConfig.enIntfSync   = VO_OUTPUT_PAL;
    stVoConfig.u32DisBufLen = 3;
    stVoConfig.enPicSize = BIG_STREAM_SIZE_BT656;
    stVoConfig.u32BgColor = COLOR_RGB_BLACK;
    s32Ret = SAMPLE_COMM_VO_StartVO(&stVoConfig);
    if (s32Ret != HI_SUCCESS) {
        SAMPLE_PRT("failed with %#x!\n", s32Ret);
        goto EXIT_VO_STOP;
    }
    //s32Ret = SAMPLE_COMM_VPSS_Bind_VO(VpssGrp, VpssChn[2], stVoConfig.VoDev, VoChn);
    //s32Ret = SAMPLE_COMM_VPSS_Bind_VO(VpssGrp, VpssChn[1], stVoConfig.VoDev, VoChn);
    // s32Ret = SAMPLE_COMM_VI_Bind_VO(ViPipe, ViChn, stVoConfig.VoDev, VoChn);
     /*vpss bind vo*/
     s32Ret = SAMPLE_COMM_VPSS_Bind_VO(VpssGrp, VpssChn[1], stVoConfig.VoDev, VoChn);//VPSS_CHN1
     if (HI_SUCCESS != s32Ret)
     {
         SAMPLE_PRT("vo bind vi failed. s32Ret: 0x%x !\n", s32Ret);
         goto EXIT_VO_STOP;
     }

    pthread_create(&VencPid, 0, CONFIG_VO_START, (HI_VOID*)&stVoConfig);
#endif

#ifdef VENC_CHN_0
   /***encode h.264 **/
    s32Ret = SAMPLE_COMM_VENC_Start(VencChn[0], enPayLoad[0],enSize[0], enRcMode,u32Profile[0],bRcnRefShareBuf,&stGopAttr);
    if (HI_SUCCESS != s32Ret)
    {
       SAMPLE_PRT("Venc Start failed for %#x!\n", s32Ret);
       goto EXIT_VI_VPSS_UNBIND;
    }

    s32Ret = SAMPLE_COMM_VPSS_Bind_VENC(VpssGrp, VpssChn[0],VencChn[0]);
    if (HI_SUCCESS != s32Ret)
    {
       SAMPLE_PRT("Venc Get GopAttr failed for %#x!\n", s32Ret);
       goto EXIT_VENC_H265_STOP;
    }
#endif
    VENC_PARAM_MOD_S pstModParam;
    memset(&pstModParam, 0x0, sizeof(pstModParam));
    pstModParam.enVencModType = MODTYPE_H264E;
    s32Ret = HI_MPI_VENC_GetModParam(&pstModParam);
    if(s32Ret != HI_SUCCESS)
    {
        SAMPLE_PRT("HI_MPI_VENC_GetModParam err for %#x!\n", s32Ret);
        return s32Ret;
    }

    printf("enVencModType:%d,stH264eModParam:%d\n",pstModParam.enVencModType,pstModParam.stH264eModParam);
    pstModParam.stH264eModParam.u32OneStreamBuffer = 1;
    pstModParam.stH264eModParam.u32H264ePowerSaveEn = 1;
    s32Ret = HI_MPI_VENC_SetModParam(&pstModParam);
    if(s32Ret != HI_SUCCESS)
    {
        SAMPLE_PRT("HI_MPI_VENC_SetModParam err for %#x!\n", s32Ret);
        return s32Ret;
    }

    /***encode h.264 **/
     s32Ret = SAMPLE_COMM_VENC_Start(VencChn[1], enPayLoad[1], enSize[1], enRcMode,u32Profile[1],bRcnRefShareBuf,&stGopAttr);
     if (HI_SUCCESS != s32Ret)
     {
         SAMPLE_PRT("Venc Start failed for %#x!\n", s32Ret);
         goto EXIT_VENC_H265_UnBind;
     }

#ifdef CVBS_EN
    // s32Ret = SAMPLE_COMM_VPSS_Bind_VENC(VpssGrp, VpssChn[0],VencChn[1]);
#else
    // s32Ret = SAMPLE_COMM_VPSS_Bind_VENC(VpssGrp, VpssChn[1],VencChn[1]);
#endif
     if (HI_SUCCESS != s32Ret)
     {
         SAMPLE_PRT("Venc bind Vpss failed for %#x!\n", s32Ret);
         goto EXIT_VENC_H264_STOP;
     }

#ifdef VPSS_LOW_DELAY
    VPSS_LOW_DELAY_INFO_S pstLowDelayInfo;
    memset(&pstLowDelayInfo, 0x0, sizeof(pstLowDelayInfo));
    s32Ret = HI_MPI_VPSS_GetLowDelayAttr(VpssGrp, VpssChn[1], &pstLowDelayInfo);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("HI_MPI_VPSS_GetLowDelayAttr failed for %#x!\n", s32Ret);
        goto EXIT_VENC_H264_STOP;
    }

    pstLowDelayInfo.bEnable = HI_TRUE;
    pstLowDelayInfo.u32LineCnt = 128;
    s32Ret = HI_MPI_VPSS_SetLowDelayAttr(VpssGrp, VpssChn[1], &pstLowDelayInfo);
    if (HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("HI_MPI_VPSS_SetLowDelayAttr failed for %#x!\n", s32Ret);
        goto EXIT_VENC_H264_STOP;
    }

    SAMPLE_PRT("start thread\n");
#endif
    
    SAMPLE_PRT("start thread\n");
    
 #ifdef VENC_GET_VENCSTREAM_PROC
    pstPara->s32Cnt = s32ChnNum;
    for(i = 0; i < s32ChnNum; ++i)
    {
        pstPara->VeChn[i] = VencChn[i];
    }
    pstPara->session = param->session;
    pstPara->gRtsplive = param->g_rtsplive;
    pstPara->sysInitStatu = *(param->sys_init_statu);
    pstPara->bThreadStart = HI_TRUE;

	pthread_create(&VencPid, 0, SAMPLE_COMM_VENC_GetVencStream_Proc, (HI_VOID*)pstPara);
   
	SAMPLE_PRT("end thread\n");
#else
    /******************************************
     stream save process
    ******************************************/
   pstPara->s32Cnt = s32ChnNum;
    for(i = 0; i < s32ChnNum; ++i)
    {
        pstPara->VeChn[i] = VencChn[i];
    }
    pstPara->session = param->session;
    pstPara->gRtsplive = param->g_rtsplive;
    pstPara->sysInitStatu = *(param->sys_init_statu);
    pstPara->VpssGrp = VpssGrp;
    pstPara->VpssChn = VpssChn[1]; //CVBS_EN
    pstPara->bThreadStart = HI_TRUE;

    pthread_create(&VencPid, 0, VENC_GetVencStreamProc, (HI_VOID*)pstPara);
    
    SAMPLE_PRT("end thread\n");
#endif

// osdShow.osd_state = 1;
#ifdef OSD_EN
    /******************************************
    OSD
    ******************************************/	
	HH_OSD_Init(); 
    init_osd_flag = 1;
	while(osd_switch){
		HH_OSD_All_Refresh();
		usleep(5000);
	}
#else
    while(1){
		usleep(5000);
	}
#endif

    printf("please press twice ENTER to exit this sample\n");
    getchar();
    getchar();

    /******************************************
     exit process
    ******************************************/
    SAMPLE_COMM_VENC_StopGetStream();

EXIT_VENC_H264_UnBind:
    SAMPLE_COMM_VPSS_UnBind_VENC(VpssGrp,VpssChn[1],VencChn[1]);
EXIT_VENC_H264_STOP:
    SAMPLE_COMM_VENC_Stop(VencChn[1]);
EXIT_VENC_H265_UnBind:
    //SAMPLE_COMM_VPSS_UnBind_VENC(VpssGrp,VpssChn[0],VencChn[0]);
EXIT_VENC_H265_STOP:
    //SAMPLE_COMM_VENC_Stop(VencChn[0]);
EXIT_VO_STOP:
    SAMPLE_COMM_VO_StopVO(&stVoConfig);
EXIT_VI_VPSS_UNBIND:
    SAMPLE_COMM_VI_UnBind_VPSS(ViPipe,ViChn,VpssGrp);
EXIT_VPSS_STOP:
    SAMPLE_COMM_VPSS_Stop(VpssGrp,abChnEnable);
EXIT_VI_STOP:
    SAMPLE_COMM_VI_StopVi(&stViConfig);
    SAMPLE_COMM_SYS_Exit();

    return s32Ret;
}


HI_VOID * SAMPLE_AUDIO_PROC(HI_VOID *arg)
{
    passing_para * param = (passing_para *)arg;

    printf("--------------*param->sys_init_statu=%d\n",*param->sys_init_statu);
    while(!(*param->sys_init_statu))
    {
        printf("waiting ---\n");
        sleep(1);
    }
    info("--------------*param->sys_init_statu=%d\n",*param->sys_init_statu);

    pthread_t audio_td;     
    // pthread_create(&audio_td, 0, SAMPLE_AUDIO_AiAenc, arg);
}

#define LWS_CALLBACK_CLIENT_WRITE (20)
struct lws *clients[10];
int g_client_count = 0;


static int callback_websocket(struct lws *wsi, enum lws_callback_reasons reason,void *user, void *in, size_t len) {
    switch (reason) 
    {
        // 客户端连接建立
        case LWS_CALLBACK_ESTABLISHED:
            printf("Client connected\n");
            if(g_client_count < 10){
                clients[g_client_count++] = wsi;
                printf("客户端连接总数：%d\n", g_client_count);
            }
            break;

        // 收到客户端消息
        case LWS_CALLBACK_RECEIVE: {
            char buf[256];
            snprintf(buf, sizeof(buf), "Server received: %s", (char *)in);
            printf("Received: %s\n", (char *)in);
            for(int i = 0; i < g_client_count; i++){
                if(clients[i] != wsi){
                    lws_write(clients[i], (unsigned char *)in, len, LWS_WRITE_TEXT);
                }
            }
            // 回显消息给客户端
            // lws_write(wsi, (unsigned char *)buf, strlen(buf), LWS_WRITE_TEXT);
            break;
        }

        // 连接关闭
        case LWS_CALLBACK_CLOSED:
            printf("Client disconnected\n");
            for(int i = 0; i < g_client_count; i++){
                if(clients[i] == wsi){
                   for(int j =i; j < g_client_count; ++j){
                     clients[j] = clients[j + 1];
                   }
                   g_client_count--;
                   break;
                }
            }
            printf("客户端连接总数：%d\n", g_client_count);
            break;

            default:
            break;
    }
    return 0;
}
static struct lws_protocols protocols[] = {
    {
        .name = "ws",
        .callback = callback_websocket,
        .per_session_data_size = 0,
        .rx_buffer_size = 1024,
    },
    { NULL, NULL, 0, 0 } // 结束标记
};

HI_VOID ws_init() {
    int port = 8000;
    struct lws_context_creation_info info;
    memset(&info, 0, sizeof(info));
    info.port = port;
    info.protocols = protocols;
    info.gid = -1;
    info.uid = -1;

    struct lws_context *context = lws_create_context(&info);
    if (!context) {
        fprintf(stderr, "Failed to create WebSocket context\n");
        return 1;
    }

    printf("Websocket server started pn ws://localhost:%d\n",port);
    while (1) {
        lws_service(context, 100);  // 50ms 事件循环
    }
    lws_context_destroy(context);
}

#define FILENAME "/nfs/current3.bmp"
#define FILENAME2 "/nfs/current4.bmp"
#define FILENAME3 "/nfs/current5.bmp"

#define WIDTH (640)
#define HIGHT (512)

static int read_hexdata_to_rgb(const uint8_t* inputFileName,uint8_t* rgb, uint8_t* outFileName, int quality){
    
    FILE *fpIn = fopen(inputFileName, "rb");
    if (!fpIn) {
        printf("无法打开文件\n");
        return -1;
    }
    
    memset(rgb, 0x0, WIDTH * HIGHT * 3);
    fread(rgb, 1, WIDTH * HIGHT * 3, fpIn);
    saveAsJPG(outFileName, rgb, WIDTH, HIGHT, quality);
    fclose(fpIn);

    return 0;
}

static int saveJpg(){
    uint8_t* rgb = (uint8_t*)malloc(WIDTH * HIGHT * 3);
    int quality = 100;
    
    read_hexdata_to_rgb(FILENAME , rgb, "output1.jpg", quality);
    read_hexdata_to_rgb(FILENAME2 , rgb, "output2.jpg", quality);
    read_hexdata_to_rgb(FILENAME3 , rgb, "output3.jpg", quality);
   
    free(rgb);
    return 0;
}

int rtc_init_rtctime_to_sys(){
    int rtc_fd = rtc_init();
    if (rtc_fd < 0) {
        perror("RTC初始化失败");
        return -1;
    }
    
    if (rtc_sync_to_system() < 0) {
        perror("RTC同步到系统时间失败");
        return -1;
    }
    printf("RTC时间已成功同步到系统\n");
    return 0;
}

int rtc_init_systime_to_rtc(){
    int rtc_fd = rtc_init();
    if (rtc_fd < 0) {
        perror("RTC初始化失败");
        return -1;
    }
    
    if (system_sync_to_rtc() < 0) {
        perror("系统同步到RTC时间失败");
        return -1;
    }
    printf("系统时间已成功同步到RTC\n");

    struct tm rtc_time; 
    if (rtc_read_time(&rtc_time) < 0) {
        return -1;
    }
    
    return 0;
}

int RecordOperation(int type, void* st) {
	if (type == RTSP_SERVER_OPERATION_RECORDING) {
		RtspServerRecordInfo* info = (RtspServerRecordInfo*)st;
        memcpy(&g_mng.record_info, info, sizeof(RtspServerRecordInfo));
		printf("mode:%d,chn:%d,filename:%s, offset_time:%d\n", info->mode, info->chn, info->filename, info->offset_time);
		if (info->mode == RTSP_SERVER_GET_RECORD_STOP && g_mng.record_flag) {
			g_mng.record_flag = 0;
		} else {
			g_mng.record_flag = 1;
		}
	} else if (type == RTSP_SERVER_OPERATION_FORCE_IDR) {
		printf("force idr chn:%d stream:%d\n", ((RtspServerForceIdr*)st)->chn, ((RtspServerForceIdr*)st)->stream_type);
	}

	return 0;
}

static void* mp4_2_h264_Proc(void* arg) {
	while (1) {

    #ifdef RTSP_RECORD
		if (!g_mng.record_flag || strlen(g_mng.record_info.filename) < 1) {
            sleep(1);
			continue;;
		}

		printf("g_mng.record_flag:%d, g_mng.record_info.filename:%s, strlen:%d\n", g_mng.record_flag, g_mng.record_info.filename, strlen(g_mng.record_info.filename));
        //添加默认路径
		int ret = streaming_thread_func(g_mng.record_info.filename);
        if(0 == ret){
            printf("play back over!\n");
            g_mng.record_flag = 0;
            memset(g_mng.record_info.filename, 0x0, sizeof(g_mng.record_info.filename));
        }

    #else
        if (!g_record.record_enable || strlen(g_record.filename) < 1) {
            sleep(1);
			continue;;
            }

            printf("g_record.record_enable:%d, g_record.filename:%s, strlen:%d\n", g_record.record_enable, g_record.filename, strlen(g_record.filename));
            //添加默认路径
            int ret = streaming_thread_func(g_record.filename);
            if(0 == ret){
                printf("play back over!\n");
                g_record.record_enable = 0;
                g_record.offset_time = 0;
                memset(g_record.filename, 0x0, sizeof(g_record.filename));
            }


            usleep(1000);
        }
    #endif
}

// // Callback function for RTSP playback requests
// void playback_callback(rtsp_client_connection_handle cc_handle, const char *record_file, int offset_time) {
//     // 打印详细的回放参数信息
//     info("========== Playback Callback Parameters ==========\n");
//     info("Callback Function Called!\n");
//     info("Client Connection Handle: %p\n", cc_handle);
//     info("Record File: %s\n", record_file ? record_file : "NULL");
//     info("Offset Time: %d seconds\n", offset_time);
//     info("==============================================\n");
//     g_record.record_enable = 1;  
//     memcpy(g_record.filename , record_file, strlen(record_file) + 1);
//     g_record.offset_time = offset_time;
// }

static void get_number(char* s, char* num) {
    int i = 0;
    int j = 0;
    for(i = 0; i < strlen(s); i++) {
        if (s[i] >= '0' && s[i] <= '9') {
            num[j++] = s[i];
        }
    }
}

static void *ldc_read_excute(void)
{
    char num[6];
    int orig_num[ldc_number];
    int set_num[ldc_number];
    int i, s32Ret, k;

    VI_LDCV3_ATTR_S ldc_attr;
    s32Ret = HI_MPI_VI_GetChnLDCV3Attr(0, 0, &ldc_attr);
    orig_num[enViewType] = ldc_attr.stAttr.enViewType;
    orig_num[s32CenterXOffset] = ldc_attr.stAttr.s32CenterXOffset;
    orig_num[s32CenterYOffset] = ldc_attr.stAttr.s32CenterYOffset;
    orig_num[s32DistortionRatio] = ldc_attr.stAttr.s32DistortionRatio;
    orig_num[s32MinRatio] = ldc_attr.stAttr.s32MinRatio;
    orig_num[bEnable] = ldc_attr.bEnable;

   
    char buffer[256];
    while(1) {
        FILE *file = fopen("/etc/conf/ldc_config", "r");
        if (file == NULL) {
            printf("open ldc_config failed\n");
        }
    check_file:
        fseek(file, 0, SEEK_SET);
        sleep(1);
        for(i = 0; i < ldc_number; i++) {
            memset(buffer, 0, sizeof(buffer));
            fgets(buffer, sizeof(buffer), file);
            if(buffer != NULL) {
                //printf("sssssssnum = %s\n", num);
                //printf("%s strlen(buffer) = %d\n", buffer, strlen(buffer));
                get_number(buffer, num);
                //printf("num = %s\n", num);
                set_num[i] = atoi(num);
                //printf("set_num = %d\n", set_num[i]);
                memset(num, 0, sizeof(num));
                if(i == bEnable) {
                    for(k = 0; k < ldc_number; k++) {
                        //printf("orgi[%d] = %d, set[%d] = %d\n", k, orig_num[k], k, set_num[k]);
                        if(orig_num[k] != set_num[k]) {
                            goto set_ldc;
                        }
                    }
                    goto check_file;
                set_ldc:
                    for(k = 0; k < ldc_number; k++) {
                        orig_num[k] = set_num[k];
                    }
                    ldc_attr.stAttr.enViewType = set_num[enViewType];
                    ldc_attr.stAttr.s32CenterXOffset = set_num[s32CenterXOffset];
                    ldc_attr.stAttr.s32CenterYOffset = set_num[s32CenterYOffset];
                    ldc_attr.stAttr.s32DistortionRatio = set_num[s32DistortionRatio];
                    ldc_attr.stAttr.s32MinRatio = set_num[s32MinRatio];
                    ldc_attr.bEnable = set_num[bEnable];
                    s32Ret = HI_MPI_VI_SetChnLDCV3Attr(0, 0, &ldc_attr);
                    if (s32Ret != HI_SUCCESS) {
                        printf("HI_MPI_VI_SetChnLDCV3Attr failed with 0x%x\n",s32Ret);
                    } else{
                        printf("set ldc success\n");
                    }
                }
            } else {
                printf("buffer is NULL\n");
            }
        }
        usleep(1);
        fclose(file);
    }
}

static void *ldc_write(void)
{
    char buf[64];
    while(1) {
        memset(buf, 0 , sizeof(buf));
        sprintf(buf, "./sample_vo %d %d", ldc_type, ldc_value);
        system(buf);
        usleep(1000);
    }
}

/******************************************************************************
* function    : main()
* Description : video venc sample
******************************************************************************/

int main_app()
{
	HI_S32 s32Ret = 0;
    int port = 554;
    struct sigaction sa;
    memset(&sa, 0, sizeof(sa));
    sa.sa_handler = handle_signal;
    sigaction(SIGINT, &sa, NULL);
    sigaction(SIGTERM, &sa, NULL);
    sigaction(SIGKILL, &sa, NULL);

	signal(SIGINT, SAMPLE_VENC_HandleSig);
	signal(SIGTERM, SAMPLE_VENC_HandleSig); 
    signal(SIGKILL, SAMPLE_VENC_HandleSig); 
	signal(SIGPIPE, SIG_IGN);//忽略tcp断开连接自动关闭

#ifdef RTSP_RECORD
    RtspServerInit(NULL, NULL);
	RtspServerStreamingRegisterInfo info[2] = {
		// 实时流
		{
			.chn = 1, 
			.stream_type = RTSP_SERVER_STREAMING_MAIN, 
			.video_info = {.use = 1, .video_type = RTSP_SERVER_VIDEO_H264, .fps = 25}
		},
		// 录像流
		{
			.chn = -1, 
			.stream_type = RTSP_SERVER_STREAMING_MAIN, 
			.video_info = {.use = 1, .video_type = RTSP_SERVER_VIDEO_H264, .fps = 25}, 
			// .audio_info = {.use = 1, .audio_type = RTSP_SERVER_AUDIO_AAC, .sample_rate = 44100, .channels = 2}
		},
	};
	RtspServerStreamingRegister(info, 2);
	RtspServerOperationRegister((void*)RecordOperation);
#else
#endif
    g_rtsplive = create_rtsp_demo(port);
	session= create_rtsp_session(g_rtsplive,"/mainstream");
    if (!session) {
        err("Failed to create live session\n");
        rtsp_del_demo(g_rtsplive);
        return -1;
    }

    // g_playback_session = create_rtsp_session(g_rtsplive, "/recording/101");
    // if (!g_playback_session) {
    //     err("Failed to create playback session\n");
    //     rtsp_del_session(g_playback_session);
    //     rtsp_del_demo(g_rtsplive);
    //     return -1;
    // } else {
    //     info("Successfully created playback session\n");
    // }
    
    // // 注册回放回调
    // rtsp_set_playback_callback(g_rtsplive, playback_callback);

    passing_para *param = (passing_para *)malloc(sizeof(passing_para));
    param->g_rtsplive = g_rtsplive;
    param->session  = session;
    param->sys_init_statu = (int *)malloc(sizeof(int));
    *(param->sys_init_statu) = 0;
    
    pthread_t video = 0;
    pthread_t audio = 0;    
    pthread_t discover = 0;
    pthread_t webservice = 0, capture = 0; 
    // pthread_t discover_pri_dev = 0, discover_pri_dev2 = 0;
    pthread_t ldc_w = 0;
    pthread_t ldc_r = 0;

#ifdef ONVIF_EN
    onvif_init();
    pthread_create(&discover, NULL, OnvifBeDiscovered, NULL);//onvif discover
	pthread_create(&webservice, NULL, OnvifWebServices, NULL);//onvif service
#endif
    //1.push_stream
    pthread_create(&video , 0, SAMPLE_VENC_1080P_CLASSIC,   (void *)param);

    //2.capture
    capture_state_init(&state);
    NetworkConfigStorageSnapParam get_snap_info;
    load_snap_info_from_ini(&get_snap_info);
    set_capture_config(&state, &get_snap_info);
    pthread_create(&capture, NULL, capture_thread, (void *)&state);
    
    // 3.playback
    pthread_t tid;
    if (pthread_create(&tid, NULL, mp4_2_h264_Proc, NULL) != 0) {
        perror("Failed to create streaming thread");
        return 1;
    }

    //4.record
    // 1. Initialize NALU Queue
    RecConfig g_config = {
        .segment_duration_sec = 300, // 5 minutes
        .storage_path = "/mnt/record_files",         // Current directory
        .queue_size = 1024,          // Queue capacity
        .video_width = 640,          // Example Width
        .video_height = 512,         // Example Height
        .video_fps = 25              // Example FPS
    };
    if (nalu_queue_init(&g_nalu_queue, g_config.queue_size) != 0) {
        fprintf(stderr, "Failed to initialize NALU queue.\n");
        return 1;
    }
    printf("NALU Queue initialized (size %d).\n", g_config.queue_size);
    memset(&g_recorder_state, 0, sizeof(RecorderState)); // Clear state struct
    g_recorder_state.queue = &g_nalu_queue;
    g_recorder_state.config = g_config; // Copy config
    g_recorder_state.running = 0;   // Changed false to 0 // Thread loop control flag
    g_recorder_state.is_recording_enabled = 0; // Changed false to 0 // Initial recording state

    //Create and start Recorder Thread
    if (pthread_create(&g_recorder_state.thread_id, NULL, recorder_thread_func, &g_recorder_state) != 0) {
        perror("Failed to create recorder thread");
        nalu_queue_destroy(&g_nalu_queue);
        return 1;
    }
    printf("Recorder thread created.\n");

#ifdef AUDIO_EN
    pthread_create(&audio , 0, SAMPLE_AUDIO_PROC, (void *)param);
#endif

    //pthread_create(&ldc_w , 0, ldc_write,  NULL);
    pthread_create(&ldc_r , 0, ldc_read_excute,  NULL);
    
    // pthread_create(&discover_pri_dev , 0, discovery_private_device,  NULL);//discovery private device
    // pthread_create(&discover_pri_dev2 , 0, discovery_private_device2,  NULL);//discovery private device
    // http_init();
    // ws_init();

    while(1)
	{
		usleep(1000);
	}
    free(param);
    free(param->sys_init_statu);

    nalu_queue_shutdown(&g_nalu_queue);
    pthread_join(g_recorder_state.thread_id, NULL); // Wait for recorder thread to exit its loop

    nalu_queue_destroy(&g_nalu_queue); // Destroy queue after thread has finished using it
	exit(s32Ret);
}

#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* End of #ifdef __cplusplus */
